package com.simple.trade.service.india.impl;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.simple.common.entity.ReqContext;
import com.simple.common.entity.ResData;
import com.simple.common.entity.constant.Payment;
import com.simple.common.entity.dto.pay.india.*;
import com.simple.common.entity.po.sys.ChannelComp;
import com.simple.common.entity.po.sys.Product;
import com.simple.common.entity.po.sys.Trade;
import com.simple.common.entity.req.india.req.IndiaWithdrawalQueryReq;
import com.simple.common.entity.req.india.req.IndiaWithdrawalReq;
import com.simple.common.entity.req.india.res.IndiaWithdrawalQueryRes;
import com.simple.common.entity.req.india.res.IndiaWithdrawalRes;
import com.simple.common.utils.Jsons;
import com.simple.trade.holder.PayContext;
import com.simple.trade.service.india.WithdrawalService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @description:
 * @author: Mr.Kang
 * @create: 2021-01-21 14:11
 **/
@Service
@Slf4j
public class WithdrawalServiceImpl extends IndiaWithdrawalBaseService<IndiaWithdrawalRes, IndiaWithdrawalRspDto> implements WithdrawalService {


    /**
     * 印度代付
     * @param req
     * @return
     */
    @Override
    public ResData<IndiaWithdrawalRes> withdrawal(IndiaWithdrawalReq req) {
        return call(req, trade -> {
            String remark1 = trade.getRemark1();
            Map<String, Object> map = Jsons.toObject(remark1, Map.class);
            map.put("subbranch", req.getSubbranch());
            map.put("originator", req.getOriginator());
            trade.setRemark1(Jsons.toJson(map));
        });
    }
    /**
     * 代付查询
     * @param req
     * @return
     */
    @Override
    public ResData<IndiaWithdrawalQueryRes> withdrawalQuery(IndiaWithdrawalQueryReq req) {
        log.info("商户订单【{}】代付结果查询{},时间为：{}", req.getOrderNo(), "开始", LocalDateTime.now());
        HashMap<String, Object> map = Maps.newHashMap();
        map.put("merchant_order_no",req.getOrderNo());
        map.put("app_id", req.getAppId());
        Trade trade = tradeApi.findByPropertyOne_(map);
        if (Objects.isNull(trade)) {
            log.info("商户订单【{}】代付结果查询{},原因为：{}", req.getOrderNo(), "异常结束", "订单不存在");
        }
        Preconditions.checkNotNull(trade, "Order does not exist, please check the order number");

        if (Trade.AuditStatus.AUDIT_SUCCESS != trade.getAuditStatus()
                ||  trade.getStatus() == Trade.Status.SUCCESS
                || trade.getStatus() == Trade.Status.FAILED) {
            IndiaWithdrawalQueryRspDto rspDto = new IndiaWithdrawalQueryRspDto();
            rspDto.setTrade(trade);
            ResData ok = ResData.ok(generateWithdrawalTradeRes(rspDto));
            log.info("商户订单【{}】代付结果查询{},响应为：{}", req.getOrderNo(), "无需查询渠道", gson.toJson(ok));
            return ok;
        }
        PayContext.current().iam(trade);
        Pair<ChannelComp, Product> pair = findChannelAnProduct();
        ChannelComp channel = pair.getLeft();
        Product product = pair.getRight();
        IndiaWithdrawalQueryDto queryDto = IndiaWithdrawalQueryDto.generateDto(trade, PayContext.current().getContext(), req.getExtra(), channel, product);
        ResData<IndiaWithdrawalQueryRspDto> rspDtoResData = forwardToChannel(queryDto, channel, Payment.PAY_TYPE.INDIA_WITHDRAWAL_QUERY, IndiaWithdrawalQueryRspDto.class);
        if (rspDtoResData.isOk()) {
            IndiaWithdrawalQueryRspDto rspDto = rspDtoResData.getData();
            Trade dtoTrade = rspDto.getTrade();
            Preconditions.checkNotNull(dtoTrade, "Order is empty, please contact customer service!!");
            tradeApi.updateById_(dtoTrade);
            ResData ok = ResData.ok(generateWithdrawalTradeRes(rspDto));
            log.info("商户订单【{}】代付结果查询{},响应为：{}", req.getOrderNo(), "成功", gson.toJson(ok));
            return ok;
        } else {
            ResData error = ResData.error(rspDtoResData.getMsg());
            log.info("商户订单【{}】代付结果查询{},响应为：{}", req.getOrderNo(), "失败", gson.toJson(error));
            return error;
        }

    }

    /**
     * 构建代付查询响应
     * @param rspDto
     * @return
     */
    private IndiaWithdrawalQueryRes generateWithdrawalTradeRes(IndiaWithdrawalQueryRspDto rspDto) {
        Trade trade = rspDto.getTrade();
        IndiaWithdrawalQueryRes res = new IndiaWithdrawalQueryRes();
        res.setSerialNo(trade.getId());
        res.setOrderNo(trade.getMerchantOrderNo());
        res.setTransferAmount(trade.getAmount());
        res.setTransferStatus(trade.getStatus());
        res.setRemark(trade.getOrderDesc());
        res.setTransferMsg(trade.getMsg());
        return res;
    }

    @Override
    protected IndiaBaseDto getDto(Trade trade, ReqContext reqContext, ChannelComp channel, Product product) {
        IndiaWithdrawalDto indiaWithdrawalDto = IndiaWithdrawalDto.generateDto(trade, reqContext, channel, product);
        return indiaWithdrawalDto;
    }

    @Override
    protected IndiaWithdrawalRes map(IndiaWithdrawalRspDto rsp) {
        Trade trade = rsp.getTrade();
        Preconditions.checkNotNull(trade, "支付失败渠道服务错误，交易不能为空");

        IndiaWithdrawalRes res = new IndiaWithdrawalRes();
        res.setTransferAmount(trade.getPayAmount());
        res.setOrderNo(trade.getMerchantOrderNo());
        res.setSerialNo(trade.getId());
        res.setRemark(trade.getOrderDesc());
        res.setTransferMsg(trade.getMsg());
        res.setTransferStatus(trade.getStatus());
        return res;
    }

}
